Popular Searches
Popular Course Categories
Popular Courses

Test Annotations

TestNG / PyTest

Test Annotations in TestNG

TestNG annotations are special Java annotations used to define, control, organize, and manage the execution lifecycle of automated test cases. In Selenium automation, TestNG annotations help determine when browser setup should happen, when test methods should execute, and when cleanup operations should be performed.

TestNG provides annotations for suite-level, test-level, class-level, method-level, and group-level configuration. These annotations help create reusable and maintainable Selenium automation frameworks by separating setup, test execution, validation, and cleanup responsibilities.

Course Resource: Selenium Training | Register for Course Demo


1. What are TestNG Annotations?

TestNG annotations are Java annotations beginning with the @ symbol that provide instructions to the TestNG framework about how and when a particular method should be executed.

For example, @Test identifies a method as a test method, @BeforeMethod performs setup before each test method, and @AfterMethod performs cleanup after each test method.

TestNG Annotations

        |

        +-- @BeforeSuite

        |

        +-- @BeforeTest

        |

        +-- @BeforeClass

        |

        +-- @BeforeMethod

        |

        +-- @Test

        |

        +-- @AfterMethod

        |

        +-- @AfterClass

        |

        +-- @AfterTest

        |

        +-- @AfterSuite


2. Why are TestNG Annotations Important?

In a Selenium automation project, tests usually require several activities before and after execution. A browser may need to be launched, an application opened, test data prepared, screenshots captured, reports generated, and the browser closed after execution.

Without annotations, these operations would have to be manually controlled inside every test method. TestNG annotations provide a structured lifecycle that makes automation code easier to organize, reuse, maintain, and scale.

  • Define test methods.
  • Perform test setup.
  • Perform test cleanup.
  • Initialize WebDriver.
  • Close WebDriver.
  • Prepare test data.
  • Configure test execution.
  • Organize test suites.
  • Group test cases.
  • Control execution behavior.
  • Support data-driven testing.
  • Support reusable framework architecture.
  • Help integrate testing with reporting and CI/CD.


3. TestNG Annotation Categories

CategoryAnnotationsPurpose
Test Annotation@TestDefines a test method
Suite Configuration@BeforeSuite, @AfterSuiteRuns around the complete suite
Test Configuration@BeforeTest, @AfterTestRuns around a TestNG XML <test> section
Class Configuration@BeforeClass, @AfterClassRuns around test methods in a class
Method Configuration@BeforeMethod, @AfterMethodRuns before and after each test method
Group Configuration@BeforeGroups, @AfterGroupsRuns around specified test groups
Data Configuration@DataProviderSupplies multiple data sets to tests


4. @Test Annotation

The @Test annotation is the primary TestNG annotation. It tells TestNG that a particular method should be treated as a test method.

import org.testng.annotations.Test;

 

public class LoginTest {

 

    @Test

    public void loginTest() {

        System.out.println("Login test executed");

    }

}

When TestNG executes this class, it identifies the method marked with @Test and executes it as a test case.

Example with Selenium

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.Assert;

import org.testng.annotations.Test;

 

public class GoogleTest {

 

    @Test

    public void verifyGoogleTitle() {

        WebDriver driver = new ChromeDriver();

 

        driver.get("https://www.google.com");

 

        Assert.assertTrue(driver.getTitle().contains("Google"));

 

        driver.quit();

    }

}


5. @BeforeSuite Annotation

@BeforeSuite executes before the tests belonging to a TestNG suite. It is intended for suite-level initialization activities.

It can be useful for initializing framework-level resources such as reporting, global configuration, test directories, or other resources that should be prepared once for the suite.

import org.testng.annotations.BeforeSuite;

 

public class SuiteSetup {

 

    @BeforeSuite

    public void beforeSuite() {

        System.out.println("Suite setup executed");

    }

}

Common Use Cases

  • Initialize reporting.
  • Create report directories.
  • Load global configuration.
  • Prepare environment-level resources.
  • Initialize framework-level services.


6. @AfterSuite Annotation

@AfterSuite executes after the tests in the relevant TestNG suite have completed.

import org.testng.annotations.AfterSuite;

 

public class SuiteCleanup {

 

    @AfterSuite

    public void afterSuite() {

        System.out.println("Suite cleanup executed");

    }

}

It can be used for final cleanup, report finalization, or releasing suite-level resources.


7. @BeforeTest Annotation

@BeforeTest executes before the TestNG XML <test> section associated with the configuration.

import org.testng.annotations.BeforeTest;

 

public class TestSetup {

 

    @BeforeTest

    public void beforeTest() {

        System.out.println("Before Test executed");

    }

}

A very important point is that @BeforeTest does not mean before every @Test method. The word "Test" here refers to the TestNG XML <test> configuration section.


8. @AfterTest Annotation

@AfterTest executes after the relevant TestNG XML <test> section has completed.

import org.testng.annotations.AfterTest;

 

public class TestCleanup {

 

    @AfterTest

    public void afterTest() {

        System.out.println("After Test executed");

    }

}

It can be used for cleanup activities associated with a TestNG XML test section.


9. @BeforeClass Annotation

@BeforeClass executes before the first test method in the current class.

import org.testng.annotations.BeforeClass;

import org.testng.annotations.Test;

 

public class LoginTest {

 

    @BeforeClass

    public void setupClass() {

        System.out.println("Class setup");

    }

 

    @Test

    public void loginTest() {

        System.out.println("Login test");

    }

 

    @Test

    public void forgotPasswordTest() {

        System.out.println("Forgot password test");

    }

}

@BeforeClass is intended for class-level initialization. It should not be confused with @BeforeMethod, which executes before every test method.


10. @AfterClass Annotation

@AfterClass executes after the test methods in the current class have completed.

import org.testng.annotations.AfterClass;

 

public class LoginTest {

 

    @AfterClass

    public void cleanupClass() {

        System.out.println("Class cleanup");

    }

}

It is useful when a resource needs to be released after class-level test execution.


11. @BeforeMethod Annotation

@BeforeMethod executes before each method annotated with @Test in the relevant class.

import org.testng.annotations.BeforeMethod;

import org.testng.annotations.Test;

 

public class LoginTest {

 

    @BeforeMethod

    public void setup() {

        System.out.println("Before every test");

    }

 

    @Test

    public void validLogin() {

        System.out.println("Valid login");

    }

 

    @Test

    public void invalidLogin() {

        System.out.println("Invalid login");

    }

}

In Selenium projects, @BeforeMethod is frequently used to create a WebDriver instance, configure the browser, and open the application before every test.


12. @AfterMethod Annotation

@AfterMethod executes after each test method.

import org.testng.annotations.AfterMethod;

import org.testng.annotations.Test;

 

public class LoginTest {

 

    @Test

    public void loginTest() {

        System.out.println("Login test");

    }

 

    @AfterMethod

    public void cleanup() {

        System.out.println("After every test");

    }

}

In Selenium automation, @AfterMethod is commonly used to capture failure evidence and close or quit the browser after every test.


13. @BeforeGroups Annotation

@BeforeGroups executes before the first test method belonging to the specified group or groups, subject to the selected suite and group configuration.

import org.testng.annotations.BeforeGroups;

import org.testng.annotations.Test;

 

public class GroupTest {

 

    @BeforeGroups("smoke")

    public void setupSmokeTests() {

        System.out.println("Smoke group setup");

    }

 

    @Test(groups = "smoke")

    public void loginTest() {

        System.out.println("Login test");

    }

 

    @Test(groups = "smoke")

    public void homePageTest() {

        System.out.println("Home page test");

    }

}


14. @AfterGroups Annotation

@AfterGroups executes after the specified group has completed, according to the applicable TestNG group configuration.

import org.testng.annotations.AfterGroups;

import org.testng.annotations.Test;

 

public class GroupCleanupTest {

 

    @Test(groups = "regression")

    public void checkoutTest() {

        System.out.println("Checkout test");

    }

 

    @AfterGroups("regression")

    public void cleanupRegression() {

        System.out.println("Regression group cleanup");

    }

}


15. Complete TestNG Annotation Lifecycle

A simplified lifecycle can be represented as follows:

@BeforeSuite

      |

      v

@BeforeTest

      |

      v

@BeforeClass

      |

      v

@BeforeMethod

      |

      v

@Test

      |

      v

@AfterMethod

      |

      v

@AfterClass

      |

      v

@AfterTest

      |

      v

@AfterSuite

This is a simplified conceptual flow. Actual execution can vary depending on the suite structure, multiple XML <test> sections, classes, groups, inheritance, dependencies, and configuration methods.


16. Complete Annotation Example

import org.testng.annotations.*;

 

public class AnnotationExample {

 

    @BeforeSuite

    public void beforeSuite() {

        System.out.println("Before Suite");

    }

 

    @BeforeTest

    public void beforeTest() {

        System.out.println("Before Test");

    }

 

    @BeforeClass

    public void beforeClass() {

        System.out.println("Before Class");

    }

 

    @BeforeMethod

    public void beforeMethod() {

        System.out.println("Before Method");

    }

 

    @Test

    public void testLogin() {

        System.out.println("Login Test");

    }

 

    @Test

    public void testSearch() {

        System.out.println("Search Test");

    }

 

    @AfterMethod

    public void afterMethod() {

        System.out.println("After Method");

    }

 

    @AfterClass

    public void afterClass() {

        System.out.println("After Class");

    }

 

    @AfterTest

    public void afterTest() {

        System.out.println("After Test");

    }

 

    @AfterSuite

    public void afterSuite() {

        System.out.println("After Suite");

    }

}


17. Execution Flow with Multiple Test Methods

@BeforeSuite

     |

     v

@BeforeTest

     |

     v

@BeforeClass

     |

     +----------------------+

     |                      |

     v                      v

@BeforeMethod          @BeforeMethod

     |                      |

     v                      v

@Test Login            @Test Search

     |                      |

     v                      v

@AfterMethod           @AfterMethod

     |                      |

     +----------+-----------+

                |

                v

          @AfterClass

                |

                v

           @AfterTest

                |

                v

           @AfterSuite


18. TestNG Annotations with Selenium WebDriver

Annotations become particularly useful when Selenium WebDriver is integrated with TestNG. Instead of creating and closing the browser separately inside every test, common setup and cleanup can be placed in configuration methods.

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.annotations.*;

 

public class BaseTest {

 

    protected WebDriver driver;

 

    @BeforeMethod

    public void setUp() {

        driver = new ChromeDriver();

        driver.manage().window().maximize();

    }

 

    @AfterMethod(alwaysRun = true)

    public void tearDown() {

        if (driver != null) {

            driver.quit();

        }

    }

}

Test Class

import org.testng.Assert;

import org.testng.annotations.Test;

 

public class HomePageTest extends BaseTest {

 

    @Test

    public void verifyGoogleTitle() {

        driver.get("https://www.google.com");

 

        Assert.assertTrue(

            driver.getTitle().contains("Google")

        );

    }

 

    @Test

    public void verifyGoogleUrl() {

        driver.get("https://www.google.com");

 

        Assert.assertTrue(

            driver.getCurrentUrl().contains("google")

        );

    }

}

Here, browser setup runs before each test and cleanup runs after each test.


19. Common @Test Annotation Attributes

The @Test annotation provides several attributes that can control test behavior.

AttributePurpose
priorityDefines relative execution priority among applicable tests
groupsAssigns a test to one or more groups
dependsOnMethodsDefines dependency on specific test methods
dependsOnGroupsDefines dependency on test groups
enabledEnables or disables a test
dataProviderConnects a test with a DataProvider
dataProviderClassSpecifies a class containing the DataProvider
timeOutDefines the maximum allowed execution time
expectedExceptionsSpecifies exception types expected from the test
descriptionProvides a description for the test
invocationCountRuns a test method multiple times
invocationTimeOutLimits the time allowed for repeated invocations
threadPoolSizeControls the thread pool for repeated invocations when applicable
alwaysRunControls execution behavior in dependency scenarios


20. @Test Priority

The priority attribute can be used to specify relative execution order among applicable test methods.

@Test(priority = 1)

public void loginTest() {

    System.out.println("Login");

}

 

@Test(priority = 2)

public void searchTest() {

    System.out.println("Search");

}

 

@Test(priority = 3)

public void logoutTest() {

    System.out.println("Logout");

}

Lower priority values are generally scheduled before higher values. However, test cases should preferably remain independent rather than relying heavily on execution order.


21. @Test Groups

The groups attribute allows test methods to be categorized.

@Test(groups = "smoke")

public void loginTest() {

    System.out.println("Login");

}

 

@Test(groups = "regression")

public void checkoutTest() {

    System.out.println("Checkout");

}

 

@Test(groups = {"smoke", "regression"})

public void searchTest() {

    System.out.println("Search");

}

Common groups include smoke, sanity, regression, functional, integration, and end-to-end.


22. @Test Enabled Attribute

The enabled attribute can enable or disable a test method.

@Test(enabled = true)

public void activeTest() {

    System.out.println("This test will execute");

}

 

@Test(enabled = false)

public void disabledTest() {

    System.out.println("This test will not execute");

}

A disabled test should be reviewed periodically so that obsolete tests do not remain permanently excluded from the suite.


23. @Test Description Attribute

The description attribute provides additional information about a test.

@Test(description = "Verify successful user login")

public void loginTest() {

    System.out.println("Login test");

}

Descriptions can improve test reports and help team members understand test intent.


24. Test Dependencies

TestNG allows test methods to depend on other test methods using dependsOnMethods.

@Test

public void loginTest() {

    System.out.println("Login successful");

}

 

@Test(dependsOnMethods = "loginTest")

public void checkoutTest() {

    System.out.println("Checkout test");

}

If the dependency does not complete successfully, the dependent test can be skipped according to TestNG's dependency behavior.

Dependencies should be used when a genuine business or technical relationship exists. Excessive dependencies can make test suites harder to maintain and execute independently.


25. dependsOnGroups

The dependsOnGroups attribute allows a test to depend on a group of tests.

@Test(groups = "login")

public void loginTest() {

    System.out.println("Login");

}

 

@Test(groups = "login")

public void sessionTest() {

    System.out.println("Session validation");

}

 

@Test(dependsOnGroups = "login")

public void checkoutTest() {

    System.out.println("Checkout");

}


26. Expected Exceptions

The expectedExceptions attribute allows a test to declare the exception type it expects to receive.

@Test(expectedExceptions = ArithmeticException.class)

public void divisionTest() {

    int result = 10 / 0;

}

If the expected exception occurs, TestNG can treat the test according to the declared expectation. This is useful when the expected behavior of a test is an exception.


27. Test Timeout

The timeOut attribute specifies the maximum time allowed for a test method.

@Test(timeOut = 5000)

public void pageTest() {

    System.out.println("Test execution");

}

For Selenium automation, synchronization should generally be handled with appropriate waits rather than using unnecessarily large test-level timeouts.


28. invocationCount Attribute

The invocationCount attribute runs the same test method multiple times.

@Test(invocationCount = 3)

public void repeatedTest() {

    System.out.println("Test executed");

}

In this example, TestNG invokes the test method three times.

Using invocationCount with threadPoolSize

@Test(invocationCount = 5, threadPoolSize = 2)

public void parallelInvocationTest() {

    System.out.println("Repeated test execution");

}

When parallel invocations are used, shared resources such as WebDriver instances must be designed for thread safety and proper isolation.


29. DataProvider Annotation

@DataProvider supplies multiple sets of data to a test method.

import org.testng.annotations.DataProvider;

import org.testng.annotations.Test;

 

public class LoginDataTest {

 

    @DataProvider(name = "loginData")

    public Object[][] loginData() {

        return new Object[][] {

            {"user1", "password1"},

            {"user2", "password2"},

            {"user3", "password3"}

        };

    }

 

    @Test(dataProvider = "loginData")

    public void loginTest(String username, String password) {

        System.out.println(username);

        System.out.println(password);

    }

}

The test method is invoked for each data set supplied by the DataProvider.


30. DataProvider with Selenium

DataProvider is useful for testing multiple usernames, passwords, search terms, product values, or other input combinations.

@DataProvider(name = "users")

public Object[][] users() {

    return new Object[][] {

        {"user1", "pass1"},

        {"user2", "pass2"},

        {"user3", "pass3"}

    };

}

 

@Test(dataProvider = "users")

public void loginTest(String username, String password) {

 

    driver.get("https://example.com/login");

 

    driver.findElement(By.id("username"))

          .sendKeys(username);

 

    driver.findElement(By.id("password"))

          .sendKeys(password);

 

    driver.findElement(By.id("login"))

          .click();

}


31. dataProviderClass Attribute

The dataProviderClass attribute can be used when the DataProvider is located in a separate class.

TestData.java

import org.testng.annotations.DataProvider;

 

public class TestData {

 

    @DataProvider(name = "loginData")

    public Object[][] loginData() {

        return new Object[][] {

            {"admin", "admin123"},

            {"user", "user123"}

        };

    }

}

LoginTest.java

import org.testng.annotations.Test;

 

public class LoginTest {

 

    @Test(

        dataProvider = "loginData",

        dataProviderClass = TestData.class

    )

    public void loginTest(String username, String password) {

        System.out.println(username + " : " + password);

    }

}


32. Annotation Inheritance

TestNG configuration methods can be defined in a base class and used by subclasses. This is especially useful for Selenium automation frameworks.

BaseTest.java

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.BeforeMethod;

 

public class BaseTest {

 

    protected WebDriver driver;

 

    @BeforeMethod

    public void setUp() {

        driver = new ChromeDriver();

    }

 

    @AfterMethod(alwaysRun = true)

    public void tearDown() {

        if (driver != null) {

            driver.quit();

        }

    }

}

LoginTest.java

import org.testng.annotations.Test;

 

public class LoginTest extends BaseTest {

 

    @Test

    public void loginTest() {

        driver.get("https://example.com/login");

        System.out.println("Login test");

    }

}

This approach prevents every test class from duplicating the same browser setup and cleanup code.


33. alwaysRun Attribute

Configuration annotations support the alwaysRun attribute. It can be useful when important cleanup should still be attempted even when preceding test or configuration conditions would otherwise affect normal execution.

@AfterMethod(alwaysRun = true)

public void tearDown() {

    if (driver != null) {

        driver.quit();

    }

}

Using alwaysRun = true for critical cleanup can help reduce the chance of leaving WebDriver sessions or other resources open.


34. @BeforeTest vs @BeforeMethod

Feature@BeforeTest@BeforeMethod
ScopeTestNG XML <test> sectionEach @Test method
FrequencyOnce for the applicable XML test configurationBefore every test method
Common UseTest-section configurationPer-test setup
Selenium ExamplePrepare test-level environmentStart/reset WebDriver


35. @BeforeClass vs @BeforeMethod

Feature@BeforeClass@BeforeMethod
ExecutionBefore the first test method in a classBefore every test method
FrequencyClass-levelMethod-level
Use CaseClass-level initializationFresh setup for every test
Selenium ExamplePrepare class-level resourceCreate or reset WebDriver


36. @BeforeSuite vs @BeforeTest vs @BeforeClass vs @BeforeMethod

AnnotationScopeTypical Usage
@BeforeSuiteEntire suiteGlobal framework setup
@BeforeTestXML <test>Test-section setup
@BeforeClassClassClass-level initialization
@BeforeMethodTest methodPer-test setup


37. Configuration Annotations with Selenium

A typical Selenium framework can organize its lifecycle using configuration annotations as follows:

@BeforeSuite

    |

    +-- Initialize reporting

    |

@BeforeTest

    |

    +-- Load test-level configuration

    |

@BeforeClass

    |

    +-- Initialize class-level resources

    |

@BeforeMethod

    |

    +-- Start WebDriver

    +-- Configure browser

    +-- Open application

    |

@Test

    |

    +-- Execute Selenium test

    +-- Perform assertions

    |

@AfterMethod

    |

    +-- Capture failure evidence

    +-- Quit WebDriver

    |

@AfterClass

    |

    +-- Release class resources

    |

@AfterTest

    |

    +-- Test-level cleanup

    |

@AfterSuite

    |

    +-- Finalize reports


38. TestNG Annotations with Page Object Model

TestNG annotations are frequently combined with the Page Object Model in Selenium automation. Page classes contain page-specific actions and locators, while TestNG controls setup, execution, validation, and cleanup.

Selenium Automation Framework

          |

          +-- TestNG

          |     |

          |     +-- @BeforeMethod

          |     +-- @Test

          |     +-- @AfterMethod

          |

          +-- Page Objects

          |     |

          |     +-- LoginPage

          |     +-- HomePage

          |

          +-- WebDriver

          |

          +-- Utilities

          |

          +-- Reports


39. Practical Login Automation Using Annotations

BaseTest.java

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.BeforeMethod;

 

public class BaseTest {

 

    protected WebDriver driver;

 

    @BeforeMethod

    public void setUp() {

        driver = new ChromeDriver();

        driver.manage().window().maximize();

        driver.get("https://example.com/login");

    }

 

    @AfterMethod(alwaysRun = true)

    public void tearDown() {

        if (driver != null) {

            driver.quit();

        }

    }

}

LoginTest.java

import org.openqa.selenium.By;

import org.testng.Assert;

import org.testng.annotations.Test;

 

public class LoginTest extends BaseTest {

 

    @Test

    public void validLoginTest() {

 

        driver.findElement(By.id("username"))

              .sendKeys("admin");

 

        driver.findElement(By.id("password"))

              .sendKeys("admin123");

 

        driver.findElement(By.id("login"))

              .click();

 

        Assert.assertTrue(

            driver.getCurrentUrl().contains("dashboard")

        );

    }

}

Execution Flow

@BeforeMethod

      |

      v

Start Browser

      |

      v

Open Login Page

      |

      v

@Test

      |

      v

Enter Username

      |

      v

Enter Password

      |

      v

Click Login

      |

      v

Assertion

      |

      v

@AfterMethod

      |

      v

Quit Browser


40. Multiple Tests Using the Same Annotations

public class LoginTest extends BaseTest {

 

    @Test

    public void validLogin() {

        System.out.println("Valid Login");

    }

 

    @Test

    public void invalidLogin() {

        System.out.println("Invalid Login");

    }

 

    @Test

    public void forgotPassword() {

        System.out.println("Forgot Password");

    }

}

With @BeforeMethod and @AfterMethod in the base class, each test can receive its own setup and cleanup cycle.


41. testng.xml with Annotations

TestNG annotations work together with the suite configuration defined in testng.xml.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">

 

<suite name="Selenium Suite">

 

    <test name="Login Tests">

        <classes>

            <class name="LoginTest"/>

        </classes>

    </test>

 

</suite>

The XML file defines the suite and test structure, while annotations define the behavior of test and configuration methods.


42. Annotation Execution Example with testng.xml

testng.xml

     |

     v

@BeforeSuite

     |

     v

@BeforeTest

     |

     v

@BeforeClass

     |

     v

@BeforeMethod

     |

     v

@Test

     |

     v

@AfterMethod

     |

     v

@AfterClass

     |

     v

@AfterTest

     |

     v

@AfterSuite


43. Common Mistakes with TestNG Annotations

Mistake 1: Forgetting @Test

public void loginTest() {

    System.out.println("Login");

}

Without @Test, the method is not identified as a normal TestNG test method.

Correct

@Test

public void loginTest() {

    System.out.println("Login");

}

Mistake 2: Using @BeforeClass When Per-Test Setup is Required

If the browser or test data must be reset before every test, @BeforeMethod is generally more appropriate than @BeforeClass.

Mistake 3: Forgetting Browser Cleanup

@AfterMethod(alwaysRun = true)

public void tearDown() {

    if (driver != null) {

        driver.quit();

    }

}

Not closing WebDriver sessions can consume system resources and create problems during large test executions.

Mistake 4: Excessive Use of Priorities

Using priority to create a large chain of dependent tests can make the suite fragile. Tests should remain independent wherever practical.

Mistake 5: Confusing @BeforeTest with @BeforeMethod

@BeforeTest relates to the TestNG XML <test> configuration, whereas @BeforeMethod executes before each test method.

Mistake 6: Sharing a WebDriver Unsafely in Parallel Execution

When tests execute in parallel, sharing one WebDriver instance between threads can cause interference. WebDriver ownership should be isolated appropriately for the chosen parallel execution strategy.


44. Best Practices for TestNG Annotations

  • Use @BeforeSuite for suite-level initialization.
  • Use @AfterSuite for suite-level cleanup.
  • Use @BeforeTest for XML test-section configuration.
  • Use @AfterTest for XML test-section cleanup.
  • Use @BeforeClass for class-level initialization.
  • Use @AfterClass for class-level cleanup.
  • Use @BeforeMethod for setup required before every test.
  • Use @AfterMethod for cleanup required after every test.
  • Use alwaysRun = true where critical cleanup should still be attempted.
  • Keep test methods independent wherever practical.
  • Use meaningful test method names.
  • Use groups to organize execution categories.
  • Use DataProvider for data-driven testing.
  • Avoid unnecessary test dependencies.
  • Keep Selenium setup and test logic properly separated.
  • Use appropriate waits instead of arbitrary sleeps.
  • Ensure WebDriver instances are properly isolated during parallel execution.


45. Test Annotations in Automation Framework Architecture

                Automation Framework

                         |

          +--------------+--------------+

          |              |              |

       TestNG         Selenium        Maven

          |

   +------+-------+

   |              |

Annotations    Assertions

   |

   +-- @BeforeSuite

   +-- @BeforeTest

   +-- @BeforeClass

   +-- @BeforeMethod

   +-- @Test

   +-- @AfterMethod

   +-- @AfterClass

   +-- @AfterTest

   +-- @AfterSuite

          |

          v

     Test Execution

          |

          v

       Reports

          |

          v

        CI/CD


46. TestNG Annotations vs Normal Java Methods

Normal Java MethodTestNG Annotated Method
Does not automatically belong to the TestNG lifecycleCan participate in the TestNG lifecycle
Requires normal Java invocationTestNG can invoke it according to configuration
No built-in TestNG test roleCan act as a test or configuration method
No TestNG execution metadataCan use TestNG attributes


47. Important TestNG Annotation Comparison

AnnotationRunsCommon Selenium Usage
@BeforeSuiteBefore the suiteInitialize framework/reporting resources
@AfterSuiteAfter the suiteFinalize reports/resources
@BeforeTestBefore XML <test>Test-level setup
@AfterTestAfter XML <test>Test-level cleanup
@BeforeClassBefore first test in classClass-level initialization
@AfterClassAfter class testsClass-level cleanup
@BeforeMethodBefore each @TestStart/reset WebDriver
@AfterMethodAfter each @TestScreenshot/quit browser
@BeforeGroupsBefore specified groupsGroup-specific setup
@AfterGroupsAfter specified groupsGroup-specific cleanup
@TestTest executionExecute Selenium scenario
@DataProviderProvides test dataData-driven Selenium tests


48. Real-World Selenium TestNG Flow

Developer

   |

   v

TestNG Test Class

   |

   v

@BeforeSuite

   |

   v

@BeforeTest

   |

   v

@BeforeClass

   |

   v

@BeforeMethod

   |

   +-- Start Browser

   +-- Configure Browser

   +-- Open Application

   |

   v

@Test

   |

   +-- Locate Elements

   +-- Perform Actions

   +-- Validate Results

   |

   v

@AfterMethod

   |

   +-- Capture Screenshot if Required

   +-- Quit Browser

   |

   v

@AfterClass

   |

   v

@AfterTest

   |

   v

@AfterSuite

   |

   v

Test Report


49. Advantages of TestNG Annotations

  • Provide a structured test lifecycle.
  • Reduce duplicate setup and cleanup code.
  • Improve test organization.
  • Make Selenium browser setup reusable.
  • Support suite-level and class-level configuration.
  • Support method-level setup and cleanup.
  • Support grouping and parameterization.
  • Work effectively with Page Object Model.
  • Help build maintainable automation frameworks.
  • Integrate effectively with Maven and CI/CD workflows.


50. Interview Questions on TestNG Annotations

Q1. What are TestNG annotations?

TestNG annotations are Java annotations used by the TestNG framework to define test methods and control different stages of test execution.

Q2. What is the most important TestNG annotation?

@Test is the primary annotation used to identify a method as a TestNG test method.

Q3. What is @BeforeMethod?

@BeforeMethod executes before each applicable test method.

Q4. What is @AfterMethod?

@AfterMethod executes after each applicable test method and is commonly used for cleanup.

Q5. What is the difference between @BeforeClass and @BeforeMethod?

@BeforeClass is used for setup before the first test method in a class, whereas @BeforeMethod runs before each test method.

Q6. What is the difference between @BeforeSuite and @BeforeTest?

@BeforeSuite runs before the relevant suite, while @BeforeTest runs in relation to the TestNG XML <test> section.

Q7. What is @AfterSuite?

@AfterSuite executes after the tests in the relevant suite have completed.

Q8. What is @BeforeGroups?

@BeforeGroups executes before the first applicable test method belonging to the specified group or groups.

Q9. Can TestNG configuration annotations be inherited?

Yes. Configuration methods can be defined in base classes and used by subclasses, which is common in Selenium automation frameworks.

Q10. Why is @BeforeMethod commonly used in Selenium?

It is commonly used to perform setup before each test, such as initializing WebDriver and opening the required application.

Q11. Why is @AfterMethod commonly used in Selenium?

It is commonly used for cleanup such as capturing failure evidence and quitting the WebDriver session.

Q12. What is alwaysRun?

alwaysRun is a TestNG configuration option that can be used when a configuration method should execute even when certain preceding conditions would otherwise prevent normal execution.

Q13. What is the difference between @BeforeTest and @BeforeClass?

@BeforeTest is associated with a TestNG XML <test> section, while @BeforeClass is associated with the lifecycle of a test class.

Q14. What is DataProvider?

@DataProvider supplies multiple sets of input data to a test method and is commonly used for data-driven testing.

Q15. What is dependsOnMethods?

dependsOnMethods defines a dependency between test methods. A dependent test can be skipped if its required dependency does not complete successfully.


51. Quick Revision

AnnotationRemember
@BeforeSuiteBefore the suite
@AfterSuiteAfter the suite
@BeforeTestBefore a TestNG XML <test> section
@AfterTestAfter a TestNG XML <test> section
@BeforeClassBefore the first test method in a class
@AfterClassAfter test methods in a class
@BeforeMethodBefore every applicable test method
@AfterMethodAfter every applicable test method
@BeforeGroupsBefore specified test groups
@AfterGroupsAfter specified test groups
@TestDefines a test method
@DataProviderSupplies test data


52. Learning Roadmap

Core Java

    |

    v

Selenium WebDriver

    |

    v

Locators

    |

    v

WebElements

    |

    v

Browser Interactions

    |

    v

Waits & Synchronization

    |

    v

TestNG

    |

    +-- @Test

    +-- @BeforeSuite

    +-- @AfterSuite

    +-- @BeforeTest

    +-- @AfterTest

    +-- @BeforeClass

    +-- @AfterClass

    +-- @BeforeMethod

    +-- @AfterMethod

    +-- @BeforeGroups

    +-- @AfterGroups

    +-- @DataProvider

    |

    v

Assertions

    |

    v

Page Object Model

    |

    v

Automation Framework

    |

    v

Maven + Git

    |

    v

Reporting

    |

    v

Jenkins / CI/CD

    |

    v

Real-Time Selenium Project


53. Summary

TestNG annotations provide the structure required to control the lifecycle of automated tests. The @Test annotation defines test methods, while configuration annotations such as @BeforeSuite, @AfterSuite, @BeforeTest, @AfterTest, @BeforeClass, @AfterClass, @BeforeMethod, @AfterMethod, @BeforeGroups, and @AfterGroups control different setup and cleanup stages.

In Selenium automation, annotations are especially useful for WebDriver initialization, browser cleanup, test data preparation, screenshots, reporting, group-specific setup, and reusable framework architecture.

Understanding the scope and behavior of each annotation is essential for building organized, maintainable, and scalable Selenium + TestNG automation frameworks.


54. Course Resources

Learn more about Selenium WebDriver, TestNG, automation frameworks, assertions, test execution, data-driven testing, and related automation concepts through the following resources:

Selenium Training

Register for Course Demo

whatsapp